home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / docs / doc2info.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-19  |  14.8 KB  |  547 lines

  1. /*
  2.  * $Id: düœR) Ëçm"ü£¶2.1 1999/08/19 14:31:53 lhecking Exp $
  3.  *
  4.  */
  5.  
  6. /* GNUPLOT - doc2info.c */
  7.  
  8. /*[
  9.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  10.  *
  11.  * Permission to use, copy, and distribute this software and its
  12.  * documentation for any purpose with or without fee is hereby granted,
  13.  * provided that the above copyright notice appear in all copies and
  14.  * that both that copyright notice and this permission notice appear
  15.  * in supporting documentation.
  16.  *
  17.  * Permission to modify the software is granted, but not the right to
  18.  * distribute the complete modified source code.  Modifications are to
  19.  * be distributed as patches to the released version.  Permission to
  20.  * distribute binaries produced by compiling modified sources is granted,
  21.  * provided you
  22.  *   1. distribute the corresponding source modifications from the
  23.  *    released version in the form of a patch file along with the binaries,
  24.  *   2. add special version identification to distinguish your version
  25.  *    in addition to the base release version number,
  26.  *   3. provide your name and address as the primary contact for the
  27.  *    support of your modified version, and
  28.  *   4. retain our contact information in regard to use of the base
  29.  *    software.
  30.  * Permission to distribute the released version of the source code along
  31.  * with corresponding source modifications in the form of a patch file is
  32.  * granted with same provisions 2 through 4 for binary distributions.
  33.  *
  34.  * This software is provided "as is" without express or implied warranty
  35.  * to the extent permitted by applicable law.
  36. ]*/
  37.  
  38. /*
  39.  * doc2info.c  -- program to convert Gnuplot .DOC format to 
  40.  *        (Emacs -) Info-file format
  41.  *
  42.  * Created by Stefan Bodewig from doc2gih by Thomas Williams 
  43.  * and doc2html by Russel Lang
  44.  * 1/29/1996
  45.  *
  46.  * usage:  doc2info gnuplot.doc gnuplot.info
  47.  *
  48.  */
  49.  
  50. /* note that tables must begin in at least the second column to */
  51. /* be formatted correctly and tabs are forbidden */
  52.  
  53. #ifdef HAVE_CONFIG_H
  54. # include "config.h"
  55. #endif
  56.  
  57. #include "ansichek.h"
  58. #include "stdfn.h"
  59.  
  60. #define MAX_LINE_LEN 1023
  61.  
  62. #include "doc2x.h"
  63. #include "xref.h"
  64.  
  65. struct BUFFER {            /* buffer to reformat paragraphs with xrefs */
  66.     char *content;
  67.     struct BUFFER *next;
  68.     struct BUFFER *prev;
  69. };
  70.  
  71. struct XREFLIST {        /* a list of xrefs allready mentioned in this node */
  72.     struct LIST *ref;
  73.     struct XREFLIST *next;
  74.     struct XREFLIST *prev;
  75. };
  76.  
  77. /* xref.c */
  78. extern struct LIST *list;
  79. extern struct LIST *head;
  80.  
  81. extern struct LIST *keylist;
  82. extern struct LIST *keyhead;
  83.  
  84. extern int maxlevel;
  85. extern int listitems;
  86.  
  87. char title[MAX_LINE_LEN+1];
  88. char ifile[MAX_LINE_LEN+1];
  89. char ofile[MAX_LINE_LEN+1];
  90. struct XREFLIST *refhead = NULL;
  91.  
  92. void convert __PROTO((FILE *, FILE *));
  93. void process_line __PROTO((char *, FILE *));
  94. void node_head __PROTO((char *, char *, char *, char *, FILE *));
  95. void name_free __PROTO((char **));
  96. char **name_alloc __PROTO(());
  97. void clear_buffer __PROTO((struct BUFFER *, FILE *));
  98. int inxreflist __PROTO((struct LIST *));
  99. void xref_free __PROTO((void));
  100.  
  101. int main(argc, argv)
  102. int argc;
  103. char **argv;
  104. {
  105.     FILE *infile;
  106.     FILE *outfile;
  107.     infile = stdin;
  108.     outfile = stdout;
  109.  
  110.     if (argc > 3) {
  111.     fprintf(stderr, "Usage: %s [infile [outfile]]\n", argv[0]);
  112.     exit(EXIT_FAILURE);
  113.     }
  114.     if (argc >= 2) {
  115.     strcpy(ifile, argv[1]);
  116.     if ((infile = fopen(argv[1], "r")) == (FILE *) NULL) {
  117.         fprintf(stderr, "%s: Can't open %s for reading\n",
  118.             argv[0], argv[1]);
  119.         exit(EXIT_FAILURE);
  120.     }
  121.     } else
  122.     safe_strncpy(ifile, "gnuplot.doc", sizeof(ifile)); /* default value */
  123.     if (argc == 3) {
  124.     safe_strncpy(ofile, argv[2], sizeof(ofile));
  125.     if ((outfile = fopen(argv[2], "w")) == (FILE *) NULL) {
  126.         fprintf(stderr, "%s: Can't open %s for writing\n",
  127.             argv[0], argv[2]);
  128.         exit(EXIT_FAILURE);
  129.     }
  130.     } else
  131.     safe_strncpy(ofile, "gnuplot.info", sizeof(ofile)); /* default value */
  132.  
  133.     safe_strncpy(title, ofile, sizeof(title));
  134.     strtok(title, ".");        /* without type */
  135.     convert(infile, outfile);
  136.     exit(EXIT_SUCCESS);
  137. }
  138.  
  139.  
  140. void convert(a, b)
  141. FILE *a, *b;
  142. {
  143.     static char line[MAX_LINE_LEN+1];
  144.  
  145.     parse(a);
  146.  
  147.     refhead = (struct XREFLIST *) xmalloc(sizeof(struct XREFLIST));
  148.     refhead->next = refhead->prev = NULL;
  149.  
  150.     /* Info header */
  151.     fprintf(b, "\
  152. This file is %s created by doc2info from %s.\n\
  153. \n\
  154. START-INFO-DIR-ENTRY\n\
  155. * Gnuplot: (gnuplot).           Gnuplot plotting program\n\
  156. END-INFO-DIR-ENTRY\n\n",
  157.         ofile, ifile);
  158.  
  159.     /* and Top node */
  160.     node_head(NULL, NULL, head->next->string, NULL, b);
  161.  
  162.     while (get_line(line, sizeof(line), a)) {
  163.     process_line(line, b);
  164.     }
  165.     list_free();
  166.     free(refhead);
  167. }
  168.  
  169. /*
  170.  * scans the lines for xrefs, creates new nodes and prints or ignores
  171.  * the rest.
  172.  *
  173.  * Info xrefs are visible. Therefore we have to reformat the paragraphs 
  174.  * containing them. All lines of the paragraph are written into a buffer
  175.  * and printed at the end of the paragraph.
  176.  */
  177. void process_line(line, b)
  178. char *line;
  179. FILE *b;
  180. {
  181.     static int line_count = 0;
  182.     struct LIST *node;        /* current node */
  183.     static struct LIST *prev = NULL;    /* previous node */
  184.     int level;            /* current level */
  185.     static char **up = NULL;    /* Array with node names */
  186.     static char **pre = NULL;
  187.     char topic[MAX_LINE_LEN+1];    /* for xrefs */
  188.     int i, j, k, l;
  189.     static int inref = FALSE;    /* flags */
  190.     static int inbold = FALSE;
  191.     static struct BUFFER *buffer;    /* buffer to hold the lines of a paragraph */
  192.     static struct BUFFER *buf_head = NULL;
  193.     int inbuf = 0;        /* offset into buffer */
  194.     char line2[3*MAX_LINE_LEN+1];    /* line of text with added xrefs */
  195.     struct LIST *reflist;
  196.     static struct XREFLIST *lastref = NULL;    /* xrefs that are already mentioned in this node */
  197.  
  198.     line2[0] = NUL;
  199.     if (!prev)            /* last node visited */
  200.     prev = head;
  201.     if (!lastref)
  202.     lastref = refhead;
  203.     if (!up) {            /* Names of `Prev:' and `Up:' nodes */
  204.     up = name_alloc();
  205.     pre = name_alloc();
  206.     strcpy(up[0], "(dir)");
  207.     strcpy(up[1], "Top");
  208.     strcpy(pre[1], "(dir)");
  209.     strcpy(pre[2], "Top");
  210.     }
  211.     line_count++;
  212.  
  213.     if (line[0] == ' ')        /* scan line for xrefs  */
  214.     for (i = 0; line[i] != NUL; ++i)
  215.         if (line[i] == '`') {    /* Reference or boldface (ignore the latter) */
  216.         if (!inref && !inbold) {
  217.             k = i + 1;    /* next character */
  218.             j = 0;    /* index into topic */
  219.             while (line[k] != '`' && line[k] != NUL)
  220.             topic[j++] = line[k++];
  221.             topic[j] = NUL;
  222.  
  223.             /* try to find the xref */
  224.             reflist = lookup(topic);
  225.             if (reflist) {
  226.             /* now we have the (key-)list-entry */
  227.             /* convert it to a list-entry that represents a node */
  228.             reflist = lkup_by_number(reflist->line);
  229.             }
  230.             /* not interested in xrefs pointing to `Top' or same node */
  231.             /* we want only one reference per topic in node */
  232.             if (reflist && reflist->level != 0 && reflist != prev && !inxreflist(reflist)) {
  233.             /* new entry to xreflist */
  234.             lastref->next = (struct XREFLIST *) xmalloc(sizeof(struct XREFLIST));
  235.             lastref->next->prev = lastref;
  236.             lastref = lastref->next;
  237.             lastref->ref = reflist;
  238.             lastref->next = NULL;
  239.             if (!buf_head) {    /* No buffer yet */
  240.                 buf_head = (struct BUFFER *) xmalloc(sizeof(struct BUFFER));
  241.                 buffer = buf_head;
  242.                 buffer->prev = NULL;
  243.                 buffer->next = NULL;
  244.             }
  245.             /* eliminate leading spaces of topic */
  246.             for (j = 0; isspace((int) reflist->string[j]); ++j);
  247.             /* encountered end of line */
  248.             if (line[k] == NUL) {
  249.                 if (line[k - 1] == '\n')    /* throw away new-lines */
  250.                 line[--k] = NUL;
  251.                 /* insert xref into line */
  252.                 sprintf(line2, "%s%s (*note %s:: )", line2, line + inbuf, reflist->string + j);
  253.                 inref = TRUE;
  254.                 /* line is done */
  255.                 break;
  256.             }
  257.             /* eliminate spaces before the second ` */
  258.             if (isspace((int) line[k - 1]))
  259.                 for (l = k - 1; line[l] != NUL; ++l)
  260.                 line[l] = line[l + 1];
  261.  
  262.             /* let `plot`s look nicer */
  263.             if (isalpha((int) line[k + 1]))
  264.                 ++k;
  265.             sprintf(line2, "%s%.*s (*note %s:: )", line2, k - inbuf + 1, line + inbuf, reflist->string + j);
  266.             /* line2 contains first inbuf characters of line */
  267.             i = inbuf = k;
  268.             } else {    /* found no reference */
  269.             inbold = TRUE;
  270.             }
  271.         } else {
  272.             if (inref)    /* inref || inbold */
  273.             inref = FALSE;
  274.             else
  275.             inbold = FALSE;
  276.         }
  277.         }
  278.     /* just copy normal characters of line with xref */
  279.         else if (inbuf) {
  280.         strncat(line2, line + i, 1);
  281.         inbuf++;
  282.         }
  283.     switch (line[0]) {        /* control character */
  284.     case '?':{            /* interactive help entry */
  285.         break;        /* ignore */
  286.     }
  287.     case '@':{            /* start/end table */
  288.         break;        /* ignore */
  289.     }
  290.     case '#':{            /* latex table entry */
  291.         break;        /* ignore */
  292.     }
  293.     case '%':{            /* troff table entry */
  294.         break;        /* ignore */
  295.     }
  296.     case '^':{            /* html entry */
  297.         break;        /* ignore */
  298.     }
  299.     case '\n':            /* empty text line */
  300.     if (buf_head) {        /* do we have a buffer? */
  301.         /* paragraph finished, print it */
  302.         clear_buffer(buf_head, b);
  303.         buffer = buf_head = NULL;
  304.     } else            /* just copy the blank line */
  305.         fputs(line, b);
  306.     break;
  307.     case ' ':{            /* normal text line */
  308.         if (buf_head) {    /* must be inserted in buffer ? */
  309.         buffer->next = (struct BUFFER *) xmalloc(sizeof(struct BUFFER));
  310.         buffer->next->prev = buffer;
  311.         buffer = buffer->next;
  312.         buffer->next = NULL;
  313.         if (line2[0] == NUL) {    /* line doesn't contain xref */
  314.             buffer->content = (char *) xmalloc(strlen(line) + 1);
  315.             strcpy(buffer->content, line);
  316.         } else {    /* line contains xref */
  317.             buffer->content = (char *) xmalloc(strlen(line2) + 1);
  318.             strcpy(buffer->content, line2);
  319.         }
  320.         } else        /* no buffer, just copy */
  321.         fputs(line, b);
  322.         break;
  323.     }
  324.     default:
  325.     if (isdigit((int) line[0])) {    /* start of section */
  326.         /* clear xref-list */
  327.         xref_free();
  328.         lastref = 0;
  329.         if (buf_head) {    /* do we have a buffer */
  330.         /* paragraphs are not allways separated by a blank line */
  331.         clear_buffer(buf_head, b);
  332.         buffer = buf_head = NULL;
  333.         }
  334.         level = line[0] - '0';
  335.  
  336.         if (level > prev->level)    /* going down */
  337.         /* so write menu of previous node */
  338.         refs(prev->line, b, "\n* Menu:\n\n", NULL, "* %s::\n");
  339.         node = prev->next;
  340.         if (!node->next) {    /* last node ? */
  341.         node_head(node->string, pre[level + 1], NULL, up[level], b);
  342.         name_free(up);
  343.         name_free(pre);
  344.  
  345.         /* next node will go up, no 'Next:' node */
  346.         } else if (node->next->level < level)
  347.         node_head(node->string, pre[level + 1], NULL, up[level], b);
  348.  
  349.         else {
  350.         node_head(node->string, pre[level + 1], node->next->string, up[level], b);
  351.         strcpy(pre[level + 1], node->string);
  352.  
  353.         /* next node will go down */
  354.         if (level < node->next->level) {
  355.             strcpy(up[level + 1], node->string);
  356.             strcpy(pre[node->next->level + 1], node->string);
  357.         }
  358.         }
  359.         prev = node;
  360.     } else
  361.         fprintf(stderr, "unknown control code '%c' in column 1, line %d\n",
  362.             line[0], line_count);
  363.     break;
  364.     }
  365. }
  366.  
  367. /*
  368.  * write the header of an Info node, treat Top node specially
  369.  */
  370. void node_head(node, prev, next, up, b)
  371. char *node, *prev, *next, *up;
  372. FILE *b;
  373. {
  374.     /* eliminate leading spaces */
  375.     while (node && isspace((int) *node))
  376.     node++;
  377.     while (next && isspace((int) *next))
  378.     next++;
  379.     while (prev && isspace((int) *prev))
  380.     prev++;
  381.     while (up && isspace((int) *up))
  382.     up++;
  383.  
  384.     if (!prev) {        /* Top node */
  385.     int i;
  386.     fprintf(b, "\nFile: %s, Node: Top, Prev: (dir), Next: %s, Up: (dir)\n\n", ofile, next);
  387.     fprintf(b, "%s\n", title);
  388.     for (i = 0; i < strlen(title); ++i)
  389.         fprintf(b, "*");
  390.     fprintf(b, "\n\n");
  391.     return;
  392.     }
  393.     fprintf(b, "\n \nFile: %s, ", ofile);
  394.     fprintf(b, "Node: %s, Prev: %s, Up: %s", node, prev, up);
  395.  
  396.     if (next)
  397.     fprintf(b, ", Next: %s\n\n", next);
  398.     else
  399.     fputs("\n\n", b);
  400. }
  401.  
  402. /*
  403.  * allocate memory for the node titles (up and prev) 
  404.  * need at most maxlevel+Top+(dir) entries
  405.  */
  406. char **name_alloc __PROTO((void))
  407. {
  408.     char **a;
  409.     int i;
  410.  
  411.     a = (char **) xmalloc((maxlevel + 2) * sizeof(char *));
  412.     for (i = 0; i <= maxlevel + 1; i++)
  413.     a[i] = (char *) xmalloc(MAX_LINE_LEN+1);
  414.     return a;
  415. }
  416.  
  417. /*
  418.  * free node names
  419.  */
  420. void name_free(names)
  421. char **names;
  422. {
  423.     int i;
  424.  
  425.     for (i = 0; i <= maxlevel + 1; i++)
  426.     free(names[i]);
  427.     free(names);
  428. }
  429.  
  430. /*
  431.  * reformat the buffered lines
  432.  */
  433. void clear_buffer(buf_head, b)
  434. struct BUFFER *buf_head;
  435. FILE *b;
  436. {
  437.     struct BUFFER *run;
  438.     int in_line = 0;        /* offset into current line */
  439.     int in_buf = 0;        /* offset into buffer */
  440.     int i, todo;
  441.     char c;
  442.  
  443.     /* for all buffer entries */
  444.     for (run = buf_head; run->next; run = run->next) {
  445.  
  446.     /* unprinted characters */
  447.     todo = strlen(run->next->content);
  448.  
  449.     /* eliminate new-lines */
  450.     if (run->next->content[todo - 1] == '\n')
  451.         run->next->content[--todo] = NUL;
  452.  
  453.     while (todo)
  454.         if (79 - in_line > todo) {    /* buffer fits into line */
  455.         fprintf(b, "%s", run->next->content + in_buf);
  456.         in_line += todo;
  457.         todo = in_buf = 0;
  458.  
  459.         } else {        /* buffer must be split over lines */
  460.  
  461.         /* search for whitespace to split at */
  462.         for (i = 79 - in_line; i > 2; --i)
  463.             if (isspace((int) (run->next->content[in_buf + i]))) {
  464.             char *beginnote, *linestart;
  465.             c = run->next->content[in_buf + i - 1];
  466.             if (c == '.')    /* don't split at end of sentence */
  467.                 continue;
  468.             if (c == ' ')    /* ditto */
  469.                 continue;
  470.  
  471.             /* dont break xref  */
  472.             /* search for xref in current line */
  473.             linestart = run->next->content + in_buf;
  474.             beginnote = strstr(linestart, "(*note");
  475.             while (beginnote && beginnote < linestart + i) {
  476.                 /* don't split if it didn't fit into the line as a whole */
  477.                 if (strchr(beginnote, ')') > linestart + i)
  478.                 break;
  479.                 /* xref is complete, maybe there's another one? */
  480.                 beginnote = strstr(beginnote + 1, "(*note");
  481.             }
  482.  
  483.             /* unbalanced xref ? */
  484.             if (beginnote && beginnote < linestart + i)
  485.                 continue;
  486.  
  487.             break;
  488.             }
  489.         if (i > 2) {    /* found a point to split buffer */
  490.             fprintf(b, "%.*s\n", i, run->next->content + in_buf);
  491.             todo -= i;
  492.             in_buf += i;
  493.             in_line = 0;
  494.         } else {    /* try with a new line */
  495.             fputs("\n", b);
  496.             in_line = 0;
  497.         }
  498.         }
  499.     }
  500.     if (in_line)        /* paragraph ended incomplete line */
  501.     fputs("\n", b);
  502.     fputs("\n", b);
  503.  
  504.     /* free the buffer */
  505.     for (run = run->prev; run->prev; run = run->prev) {
  506.     free(run->next->content);
  507.     free(run->next);
  508.     run->next = NULL;
  509.     }
  510.     if (buf_head->next) {
  511.     free(buf_head->next->content);
  512.     free(buf_head->next);
  513.     buf_head->next = NULL;
  514.     }
  515.     free(buf_head);
  516. }
  517.  
  518. /*
  519.  * test whether topic is allready referenced in node
  520.  */
  521. int inxreflist(reflist)
  522. struct LIST *reflist;
  523. {
  524.     struct XREFLIST *run;
  525.  
  526.     for (run = refhead; run->next; run = run->next)
  527.     if (run->next->ref == reflist)
  528.         return TRUE;
  529.     return FALSE;
  530. }
  531.  
  532. /*
  533.  * free the list of xrefs
  534.  */
  535. void xref_free __PROTO((void))
  536. {
  537.     struct XREFLIST *lastref;
  538.  
  539.     for (lastref = refhead; lastref->next; lastref = lastref->next);
  540.     if (lastref != refhead)
  541.     for (lastref = lastref->prev; lastref->prev; lastref = lastref->prev)
  542.         free(lastref->next);
  543.     if (refhead->next)
  544.     free(refhead->next);
  545.     refhead->next = NULL;
  546. }
  547.